package cn.dgiot.fd.service.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aliyun.oss.common.utils.StringUtils;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.iot.model.v20180120.CreateOTAFirmwareRequest;
import com.aliyuncs.iot.model.v20180120.CreateOTAFirmwareResponse;
import com.aliyuncs.iot.model.v20180120.CreateOTAModuleRequest;
import com.aliyuncs.iot.model.v20180120.CreateOTAModuleResponse;
import com.aliyuncs.iot.model.v20180120.CreateOTAStaticUpgradeJobRequest;
import com.aliyuncs.iot.model.v20180120.CreateOTAStaticUpgradeJobResponse;
import com.aliyuncs.iot.model.v20180120.CreateOTAVerifyJobRequest;
import com.aliyuncs.iot.model.v20180120.CreateOTAVerifyJobResponse;
import com.aliyuncs.iot.model.v20180120.DeleteOTAFirmwareRequest;
import com.aliyuncs.iot.model.v20180120.DeleteOTAFirmwareResponse;
import com.aliyuncs.iot.model.v20180120.DeleteOTAModuleRequest;
import com.aliyuncs.iot.model.v20180120.DeleteOTAModuleResponse;
import com.aliyuncs.iot.model.v20180120.GenerateOTAUploadURLRequest;
import com.aliyuncs.iot.model.v20180120.GenerateOTAUploadURLResponse;
import com.aliyuncs.iot.model.v20180120.ListOTAModuleByProductRequest;
import com.aliyuncs.iot.model.v20180120.ListOTAModuleByProductResponse;
import com.aliyuncs.iot.model.v20180120.UpdateOTAModuleRequest;
import com.aliyuncs.iot.model.v20180120.UpdateOTAModuleResponse;

import cn.dgiot.fd.contant.AliyunConfig;
import cn.dgiot.fd.contant.SysConfig;
import cn.dgiot.fd.model.DeviceUpgradeFlowModel;
import cn.dgiot.fd.model.DeviceUpgradeModel;
import cn.dgiot.fd.model.FileModel;
import cn.dgiot.fd.model.OTAModel;
import cn.dgiot.fd.service.IDeviceUpgradeFlowService;
import cn.dgiot.fd.service.IDeviceUpgradeService;
import cn.dgiot.fd.service.IFileService;
import cn.dgiot.fd.service.IOTAService;

/**
 * [设备升级]
 * @author
 *
 */
@Service
public class OTAServiceImpl extends BaseServiceImpl implements IOTAService{

	private Logger logger = LoggerFactory.getLogger(OTAServiceImpl.class);
	
	@Autowired
	private AliyunConfig aliyunConfig;
	
	@Autowired
	private SysConfig sysConfig;
	
	@Autowired
	private IFileService fileService;
	 
	@Autowired
	private IDeviceUpgradeService deviceUpgradeService;
	
	@Autowired
	private IDeviceUpgradeFlowService deviceUpgradeFlowService;	
	
	@Override
	public GenerateOTAUploadURLResponse generateOTAUploadURL() {
		 
		GenerateOTAUploadURLRequest request = new GenerateOTAUploadURLRequest();
		request.setFileSuffix("bin");
		GenerateOTAUploadURLResponse response = new GenerateOTAUploadURLResponse();
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("生成升级包文件失败");
			logger.error("-----------生成升级包文件异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("生成升级包文件失败");
			logger.error("-----------生成升级包文件异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}
	

	@Override
	public CreateOTAFirmwareResponse createOTAFirmware(OTAModel otaModel) {
		CreateOTAFirmwareRequest request = new CreateOTAFirmwareRequest();
		CreateOTAFirmwareResponse createOTAFirmwareResponse = new CreateOTAFirmwareResponse();
		// 调用该接口生成升级包文件上传到OSS的URL及详细信息
		GenerateOTAUploadURLResponse generateOTAUploadURLResponse = generateOTAUploadURL();
		Date requestTime = null;
		Date responseTime = null;
		if(generateOTAUploadURLResponse!= null && generateOTAUploadURLResponse.getSuccess()) {
			String firmwareUrl = generateOTAUploadURLResponse.getData().getFirmwareUrl();
			boolean flag = uploadFileToBucket(otaModel,generateOTAUploadURLResponse);
			if(flag) {
				otaModel.setFirmwareUrl(firmwareUrl);
				request.setDestVersion(otaModel.getDestVersion());
				request.setFirmwareDesc(otaModel.getFirmwareDesc());
				request.setFirmwareName(otaModel.getFirmwareName());
				request.setFirmwareUrl(otaModel.getFirmwareUrl());
				request.setProductKey(aliyunConfig.productKey);
				request.setNeedToVerify(false);
				request.setType(otaModel.getType());
				request.setModuleName(otaModel.getModuleName());
				CreateOTAFirmwareResponse response = new CreateOTAFirmwareResponse();
				
				try {
					requestTime = new Date();
					response = getDefaultAcsClient().getAcsResponse(request);
					responseTime = new Date();
				} catch (ServerException e) {
					response.setSuccess(false);
					response.setErrorMessage("创建升级包失败");
					logger.error("-----------创建升级包异常--------------------------",e);
				} catch (ClientException e) {
					response.setSuccess(false);
					response.setErrorMessage("创建升级包失败");
					logger.error("-----------创建升级包异常--------------------------",e);
				}
				return response;
			}else {
				createOTAFirmwareResponse.setSuccess(false);
				createOTAFirmwareResponse.setErrorMessage("升级包上传失败或文件不存在");
			}
		}else {
			createOTAFirmwareResponse.setSuccess(false);
			createOTAFirmwareResponse.setErrorMessage("创建升级包失败");
		}
		this.addAliyunApiLog(request, requestTime, createOTAFirmwareResponse, responseTime, aliyunConfig.productKey , "", createOTAFirmwareResponse.getSuccess());
		return createOTAFirmwareResponse;
	}
	
	@Override
	public boolean uploadFileToBucket(OTAModel otaModel,GenerateOTAUploadURLResponse generateOTAUploadURLResponse) {
		
		String key = generateOTAUploadURLResponse.getData().getKey();
		String accessKey = generateOTAUploadURLResponse.getData().getOSSAccessKeyId();
		String policy = generateOTAUploadURLResponse.getData().getPolicy();
		String signature = generateOTAUploadURLResponse.getData().getSignature();
		// 在URL中添加存储空间名称，添加后URL如下：http://yourBucketName.oss-cn-hangzhou.aliyuncs.com。
        String host = generateOTAUploadURLResponse.getData().getHost();
        String filePath = sysConfig.uploadPath;
       
        CloseableHttpClient  httpClient = HttpClients.createDefault();
        HttpPost uploadFile = new HttpPost(host);
        InputStream is = null;
		try {
			FileModel fileInfo = fileService.getFileById(new FileModel(otaModel.getFileId()));
			if(fileInfo == null) {
				return false;
			}
			String fileName = fileInfo.getFileName();
//			is = new FileInputStream("d:/t.bin");
			is = new FileInputStream(filePath+fileName);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addTextBody("key", key, org.apache.http.entity.ContentType.TEXT_PLAIN);
        builder.addTextBody("policy", policy, ContentType.TEXT_PLAIN);
        builder.addTextBody("OSSAccessKeyId", accessKey, ContentType.TEXT_PLAIN);
        builder.addTextBody("signature", signature, ContentType.TEXT_PLAIN);
        builder.addTextBody("success_action_status", "200", ContentType.TEXT_PLAIN);
        builder.addBinaryBody("file",is);
        HttpEntity multipart = builder.build();
        uploadFile.setEntity(multipart);
        CloseableHttpResponse response = null;
		try {
			response = httpClient.execute(uploadFile);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} finally{
			try {
				is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

        if (response.getStatusLine().getStatusCode() == 200) {
          return true;
        }

        return false;
        
	}


	@Override
	public CreateOTAVerifyJobResponse createOTAVerifyJob(OTAModel otaModel) {
		
		CreateOTAVerifyJobResponse response = new CreateOTAVerifyJobResponse();
		/** 固件id */
		String firmwareId = otaModel.getFirmwareId();
		/** 检测设备 */
		List<String> targetDeviceNames = otaModel.getTargetDeviceNames();
		
		if(StringUtils.isNullOrEmpty(firmwareId)) {
			response.setSuccess(false);
			response.setErrorMessage("固件id不为空");
			return response;
		}
		if(targetDeviceNames != null 
				&& (targetDeviceNames.size() == 0 || targetDeviceNames.size() > 10 )) {
			response.setSuccess(false);
			response.setErrorMessage("待验证的设备不能为空并且不能超过10个");
			return response;
		}
		
		Integer timeoutInMinutes = otaModel.getTimeoutInMinutes();
		CreateOTAVerifyJobRequest request = new CreateOTAVerifyJobRequest();
		request.setFirmwareId(firmwareId);
		request.setTargetDeviceNames(targetDeviceNames);
		request.setTimeoutInMinutes(timeoutInMinutes);
		 
		
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("固件验证任务失败");
			logger.error("-----------固件验证任务异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("固件验证任务失败");
			logger.error("-----------固件验证任务异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}


	@Override
	public CreateOTAStaticUpgradeJobResponse createOTAStaticUpgradeJob(OTAModel otaModel) {

		CreateOTAStaticUpgradeJobResponse response = new CreateOTAStaticUpgradeJobResponse();
		/** 产品key */
		String productKey = aliyunConfig.productKey;
		/** 固件id */
		String firmwareId = otaModel.getFirmwareId();
		/** 升级范围 */
		String targetSelection = otaModel.getTargetSelection();
		/** 设备升级失败后，自动重试的时间间隔 */
		Integer retryInterval = otaModel.getRetryInterval();
		/** 自动重试次数 */
		Integer retryCount = otaModel.getRetryCount();
		/** 是否覆盖之前的升级任务 */
		Integer overwriteMode = otaModel.getOverwriteMode();
		/** 定向升级的设备名称列表 */
		List<String> targetDeviceNames = otaModel.getTargetDeviceNames();
		
		if(StringUtils.isNullOrEmpty(firmwareId)) {
			response.setSuccess(false);
			response.setErrorMessage("升级包ID不为空");
			return response;
		}
		if(StringUtils.isNullOrEmpty(targetSelection)) {
			response.setSuccess(false);
			response.setErrorMessage("升级范围不为空");
			return response;
		}
		if(retryInterval!= null && retryCount==null) {
			response.setSuccess(false);
			response.setErrorMessage("如果传入RetryInterval参数，则需传入该参数");
			return response;
		}
		if(targetDeviceNames != null 
				&& (targetDeviceNames.size() == 0 || targetDeviceNames.size() > 100000 )) {
			response.setSuccess(false);
			response.setErrorMessage("待验证的设备不能为空并且不能超过100000个");
			return response;
		}
		
		Integer timeoutInMinutes = otaModel.getTimeoutInMinutes();
		CreateOTAStaticUpgradeJobRequest request = new CreateOTAStaticUpgradeJobRequest();
		request.setProductKey(productKey);
		request.setFirmwareId(firmwareId);
		request.setTargetSelection(targetSelection);
		request.setRetryInterval(retryInterval);
		request.setRetryCount(retryCount);
		request.setOverwriteMode(overwriteMode);
		request.setTargetDeviceNames(targetDeviceNames);
		request.setTimeoutInMinutes(timeoutInMinutes);
		 
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
			if(response != null && response.getSuccess()) {
				DeviceUpgradeFlowModel deviceUpgradeFlowModel = new DeviceUpgradeFlowModel();
				deviceUpgradeFlowModel.setProductKey(productKey);
				deviceUpgradeFlowModel.setDeviceNames(targetDeviceNames);
				deviceUpgradeFlowModel.setJobId(response.getData().getJobId());
				deviceUpgradeFlowModel.setStatus("0");
				deviceUpgradeFlowModel.setCreateTime(new Timestamp(new Date().getTime()));
				deviceUpgradeFlowService.insertDeviceUpgrade(deviceUpgradeFlowModel);
				deviceUpgradeService.insertDeviceUpgrade(new DeviceUpgradeModel(deviceUpgradeFlowModel));
			}
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("创建静态升级批次失败");
			logger.error("-----------创建静态升级批次异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("创建静态升级批次失败");
			logger.error("-----------创建静态升级批次异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, productKey , StringUtils.join(",", targetDeviceNames), response.getSuccess());
		return response;
	}


	@Override
	public DeleteOTAFirmwareResponse deleteOTAFirmware(OTAModel otaModel) {

		DeleteOTAFirmwareResponse response = new DeleteOTAFirmwareResponse();
		/** 固件id */
		String firmwareId = otaModel.getFirmwareId();
		 
		if(StringUtils.isNullOrEmpty(firmwareId)) {
			response.setSuccess(false);
			response.setErrorMessage("升级包id不为空");
			return response;
		}
		  
		DeleteOTAFirmwareRequest request = new DeleteOTAFirmwareRequest();
		request.setFirmwareId(firmwareId);
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("删除升级包失败");
			logger.error("-----------删除升级包异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("删除升级包失败");
			logger.error("-----------删除升级包异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}


	@Override
	public CreateOTAModuleResponse createOTAModule(OTAModel otaModel) {
		
		CreateOTAModuleResponse response = new CreateOTAModuleResponse();
		/** 模块名称 */
		String moduleName = otaModel.getModuleName();
		/** 别名 */
		String aliasName = otaModel.getAliasName();
		/** 描述 */
		String desc = otaModel.getDesc();
		 
		if(StringUtils.isNullOrEmpty(moduleName)) {
			response.setSuccess(false);
			response.setErrorMessage("模块名称不为空");
			return response;
		}
		  
		CreateOTAModuleRequest request = new CreateOTAModuleRequest();
		request.setModuleName(moduleName);
		request.setAliasName(aliasName);
		request.setDesc(desc);
		request.setProductKey(aliyunConfig.productKey);
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("创建模块失败");
			logger.error("-----------创建模块异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("创建模块失败");
			logger.error("-----------创建模块异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}


	@Override
	public UpdateOTAModuleResponse updateOTAModule(OTAModel otaModel) {
		
		UpdateOTAModuleResponse response = new UpdateOTAModuleResponse();
		/** 模块名称 */
		String moduleName = otaModel.getModuleName();
		/** 别名 */
		String aliasName = otaModel.getAliasName();
		/** 描述 */
		String desc = otaModel.getDesc();
		 
		if(StringUtils.isNullOrEmpty(moduleName)) {
			response.setSuccess(false);
			response.setErrorMessage("模块名称不为空");
			return response;
		}
		  
		UpdateOTAModuleRequest request = new UpdateOTAModuleRequest();
		request.setModuleName(moduleName);
		request.setAliasName(aliasName);
		request.setDesc(desc);
		request.setProductKey(aliyunConfig.productKey);
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("修改模块失败");
			logger.error("-----------修改模块异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("修改模块失败");
			logger.error("-----------修改模块异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}


	@Override
	public DeleteOTAModuleResponse deleteOTAModule(OTAModel otaModel) {
		
		DeleteOTAModuleResponse response = new DeleteOTAModuleResponse();
		/** 模块名称 */
		String moduleName = otaModel.getModuleName();
		 
		if(StringUtils.isNullOrEmpty(moduleName)) {
			response.setSuccess(false);
			response.setErrorMessage("模块名称不为空");
			return response;
		}
		  
		DeleteOTAModuleRequest request = new DeleteOTAModuleRequest();
		request.setModuleName(moduleName);
		request.setProductKey(aliyunConfig.productKey);
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("删除模块失败");
			logger.error("-----------删除模块异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("删除模块失败");
			logger.error("-----------删除模块异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}


	@Override
	public ListOTAModuleByProductResponse listOTAModuleByProduct(OTAModel otaModel) {
		
		ListOTAModuleByProductResponse response = new ListOTAModuleByProductResponse();
		  
		ListOTAModuleByProductRequest request = new ListOTAModuleByProductRequest();
		request.setProductKey(aliyunConfig.productKey);
		
		Date requestTime = null;
		Date responseTime = null;
		try {
			requestTime = new Date();
			response = getDefaultAcsClient().getAcsResponse(request);
			responseTime = new Date();
		} catch (ServerException e) {
			response.setSuccess(false);
			response.setErrorMessage("查询产品模块列表失败");
			logger.error("-----------查询产品模块列表异常--------------------------",e);
		} catch (ClientException e) {
			response.setSuccess(false);
			response.setErrorMessage("查询产品模块列表失败");
			logger.error("-----------查询产品模块列表异常--------------------------",e);
		}
		this.addAliyunApiLog(request, requestTime, response, responseTime, "" , "", response.getSuccess());
		return response;
	}
	
	

}
